package com.invengo.module_check.ui.fragment.find_error;

import android.app.Application;
import android.os.Build;
import android.text.TextUtils;

import androidx.annotation.NonNull;
import androidx.databinding.ObservableArrayList;
import androidx.databinding.ObservableList;

import com.invengo.library_db.entity.module_check.BookBean;
import com.invengo.library_db.entity.module_check.ShelfBean;
import com.invengo.library_rfid.classify.AnalyzeImpl;
import com.invengo.library_rfid.classify.RFIDCallBackListener;
import com.invengo.library_rfid.entity.TagInfo;
import com.invengo.module_check.BR;
import com.invengo.module_check.R;
import com.invengo.module_check.data.repsitory.business.BusinessRepsitory;
import com.invengo.module_check.ui.fragment.find_error.item.FindErrorItmeViewModel;
import com.invengo.module_check.ui.fragment.guide_listing.item.ListingGuideItmeViewModel;

import java.util.List;
import java.util.stream.Collectors;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import java8.util.stream.StreamSupport;
import me.goldze.mvvmhabit.base.BaseViewModel;
import me.goldze.mvvmhabit.binding.command.BindingCommand;
import me.goldze.mvvmhabit.bus.event.SingleLiveEvent;
import me.goldze.mvvmhabit.http.BaseBean;
import me.goldze.mvvmhabit.utils.KLog;
import me.goldze.mvvmhabit.utils.RxUtils;
import me.goldze.mvvmhabit.utils.ToastUtils;
import me.tatarka.bindingcollectionadapter2.BindingRecyclerViewAdapter;
import me.tatarka.bindingcollectionadapter2.ItemBinding;

public class FindErrorViewModel extends BaseViewModel<BusinessRepsitory> {
    public RFIDCallBackListener rfidService = new RFIDCallBackListener(AnalyzeImpl.TO_BOOK, tagInfo -> onScanResult(tagInfo), state -> isReading.set(state));

    public SingleLiveEvent<Integer> scanTotall = new SingleLiveEvent<>();
    public SingleLiveEvent<Integer> normalCount = new SingleLiveEvent<>();
    public SingleLiveEvent<Integer> warningCount = new SingleLiveEvent<>();
    public BindingRecyclerViewAdapter adapter = new BindingRecyclerViewAdapter();
    public ObservableList<FindErrorItmeViewModel> bookItemList = new ObservableArrayList<>();
    public ItemBinding<FindErrorItmeViewModel> bookitemBinding = ItemBinding.of(BR.viewModel, R.layout.item_find_error);

    public FindErrorViewModel(@NonNull Application application) {
        super(application, BusinessRepsitory.getInstance());
        registerRFID(rfidService);
        scanTotall.postValue(0);
        normalCount.postValue(0);
        warningCount.postValue(0);
    }

    public void onScanResult(TagInfo tagInfo) {
        switch (tagInfo.getRfidModel()) {
            case TID:
                if (tagInfo.getScanModel() == AnalyzeImpl.TO_SHELF) {
//                    getShelfByTid(tagInfo.getTag());
                } else {
                    checkErrorTag(tagInfo.getTid());
//                    getBookByTid(tagInfo.getTag());
                }
                break;
            case EPC:
            case U_DATA:

                if (tagInfo.getScanModel() == AnalyzeImpl.TO_SHELF) {
//                    getShelfByCode(tagInfo.getTag());
                } else
                    checkErrorTagByBarCode(tagInfo.getTag(), tagInfo.getTid());
                break;
        }
    }

    /**
     * 按Tid查询书本
     *
     * @param tid 标签
     */
    private void getBookByTid(String tid) {
        model.getBookByTid(tid)
                .compose(RxUtils.applySchedulersIO(getLifecycleProvider(), this))
                .subscribe(bookBean -> addItem(bookBean));

    }

    private void checkErrorTagByBarCode(String barcode, String tid) {
        Observable<BaseBean<BookBean>> bookByBarCode = model.getBookByCode(barcode);
        Observable<BaseBean<ShelfBean>> shelfInfoByBarCode = model.getShelfInfoByTid(barcode);
        Observable<String> tidOberservable = Observable.just(tid);
        Observable.zip(bookByBarCode, shelfInfoByBarCode, tidOberservable,  Observable.just(barcode), (baseBook, baseShelf, tids, bb) -> {
                    if (baseBook.isOk()) {
                        return baseBook.getData();
                    } else {
                        if (baseShelf.isOk()) {
                            return null;
                        } else {
                            BookBean bean = new BookBean();
                            bean.setTid(tids);
                            bean.setBarCode(bb);
                            return bean;
                        }
                    }
                })
                .subscribeOn(Schedulers.io())
                .compose(RxUtils.bindToLifecycle(getLifecycleProvider()))
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(bean -> addItem(bean), throwable -> KLog.e("异常： " + throwable.getMessage()));
    }

    private void checkErrorTag(String tid) {
        Observable<BaseBean<BookBean>> bookByTid = model.getBookByTid(tid);
        Observable<BaseBean<ShelfBean>> shelfInfoByTid = model.getShelfInfoByTid(tid);
        Observable<String> tidOberservable = Observable.just(tid);
        Observable.zip(bookByTid, shelfInfoByTid, tidOberservable, (baseBook, baseShelf, tids) -> {
                    if (baseBook.isOk()) {
                        return baseBook.getData();
                    } else {
                        if (baseShelf.isOk()) {
                            return null;
                        } else {
                            BookBean bean = new BookBean();
                            bean.setTid(tids);
                            return bean;
                        }
                    }
                })
                .subscribeOn(Schedulers.io())
                .compose(RxUtils.bindToLifecycle(getLifecycleProvider()))
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(bean -> {
                    addItem(bean);
                }, throwable -> {
                    KLog.e("异常： " + throwable.getMessage());
                });
    }

    /**
     * 添加项目
     *
     * @param bean 豆
     */
    private void addItem(BookBean bean) {
        scanTotall.setValue(scanTotall.getValue() + 1);
        if (!TextUtils.isEmpty(bean.getBookName())) {
            bookItemList.add(new FindErrorItmeViewModel(this, bean));
            normalCount.setValue(normalCount.getValue() + 1);
        } else {
            bookItemList.add(0, new FindErrorItmeViewModel(this, bean));
            warningCount.setValue(warningCount.getValue() + 1);
        }
    }


    /**
     * 清除所有数据
     */
    public BindingCommand cleanAllData = new BindingCommand(() -> {
        cleanRFIDCacheNotStop();
        bookItemList.clear();
        normalCount.postValue(0);
        scanTotall.postValue(0);
        warningCount.postValue(0);
    });
    /**
     * 清除所有数据
     */
    public BindingCommand finishCommand = new BindingCommand(() -> {
        getUC().getFinishEvent().call();
    });

    public void onItemRemove(FindErrorItmeViewModel bean) {
        BookBean bookBean = bean.book.getValue();
        Minus(bookBean);
        int position = bookItemList.indexOf(bean);
        bookItemList.remove(position);
        adapter.notifyDataSetChanged();
        ToastUtils.showShort("删除成功");
    }

    private void Minus(BookBean bean) {
        if (!TextUtils.isEmpty(bean.getShelfCode())) {
            normalCount.setValue(normalCount.getValue() - 1);
        } else {
            warningCount.setValue(warningCount.getValue() - 1);
        }
        scanTotall.setValue(scanTotall.getValue() - 1);
    }

    public int getPosition(FindErrorItmeViewModel item) {
        return bookItemList.indexOf(item);
    }

    public List<BookBean> getMatchBooks() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return bookItemList.stream()
                    .map(viewModel -> viewModel.book.getValue())
                    .collect(Collectors.toList());
        } else {
            return StreamSupport.stream(bookItemList)
                    .map(viewModel -> viewModel.book.getValue())
                    .collect(java8.util.stream.Collectors.toList());
        }
    }
}
